#pragma once

#include <limits.h>

#include "Types.h"



namespace MemMgr
{
	class StackAllocator
	{
	public:

		typedef AtomSizeU* PtrType;
		typedef T_U32 Marker;

		struct MarkerFields
		{
			MarkerFields(const Marker iMarker):
				mStackOffset(iMarker & 0x7fffffff),
				mStackNum(iMarker >> 31)
			{
			}

			MarkerFields(const size_t iStackOffset, const size_t iStackNum):
				mStackOffset(iStackOffset),
				mStackNum(iStackNum)
			{
			}

			inline operator Marker() const
			{
				return mStackNum << 31 | mStackOffset;
			}

			Marker mStackOffset : 31;
			Marker mStackNum : 1;
		};

		explicit StackAllocator(void* iPoolPtr, const size_t iPoolSize);
		~StackAllocator(void);

		void* Allocate(const size_t iSize, const Marker iMarker);
		void FreeToMarker(const Marker iMarker);

		Marker GetLowerStackMarker(void) const;
		Marker GetUpperStackMarker(void) const;

		void Clear();

	private:

		PtrType mBasePtr;
		PtrType mTopPtr;
		PtrType mLowerStackPtr;
		PtrType mUpperStackPtr;
		
		StackAllocator(const StackAllocator& iOther); // Not implemented
		StackAllocator& operator=(const StackAllocator& iOther); // Not implemented
	};
};